package sharemem

import (
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/protoc/pb"
	"sort"
	"strconv"
	"strings"
	"sync/atomic"
)

type Team struct {
	Id             MyInt32  // 队伍id
	Name           [10]rune // 队伍名称
	FightRoleList  [4]int32 // 战斗角色列表
	AssistRoleList [2]int32 // 支援角色列表
}

func (t *Team) MemInit() {
	t.Id.NewVal = 0
	t.Id.OldVal = 0
	t.Id.Status = 0
	for i := 0; i < len(t.Name); i++ {
		t.Name[i] = 0
	}
	for i := 0; i < len(t.FightRoleList); i++ {
		t.FightRoleList[i] = 0
	}
	for i := 0; i < len(t.AssistRoleList); i++ {
		t.AssistRoleList[i] = 0
	}
}

func (t *Team) IsUse() bool {
	return t.Id.NewVal != 0 || t.Id.OldVal != 0
}

func (t *Team) GetId() int32 {
	return t.Id.NewVal
}

func (t *Team) SetSync() {
	atomic.AddUint32(&(t.Id.Status), 1)
}

func (t *Team) GetName() string {
	var name strings.Builder
	for _, v := range t.Name {
		if v == 0 {
			break
		}
		name.WriteRune(v)
	}
	return name.String()
}

func (t *Team) SetName(name string) {
	for i := 0; i < len(t.Name); i++ {
		t.Name[i] = 0
	}
	i := 0
	for _, v := range name {
		if i == len(t.Name) {
			logger.Error("name too long, name: %v", name)
			return
		}
		t.Name[i] = v
		i++
	}
}

func (t *Team) GetActiveTeamListAll() []int32 {
	var teamList = make([]int32, 0)
	teamList = append(teamList, t.GetFightRoleList()...)
	teamList = append(teamList, t.GetAssistRoleList()...)
	return teamList
}

func (t *Team) GetFightRoleList() []int32 {
	roleIdList := make([]int32, 0)
	for _, v := range t.FightRoleList {
		roleIdList = append(roleIdList, v)
	}
	return roleIdList
}

func (t *Team) SetFightRoleList(roleIdList []int32) {
	for i := 0; i < len(t.FightRoleList); i++ {
		t.FightRoleList[i] = 0
	}
	for index, roleId := range roleIdList {
		t.FightRoleList[index] = roleId
	}
}

func (t *Team) GetAssistRoleList() []int32 {
	roleIdList := make([]int32, 0)
	for _, v := range t.AssistRoleList {
		roleIdList = append(roleIdList, v)
	}
	return roleIdList
}

func (t *Team) SetAssistRoleList(roleIdList []int32) {
	for i := 0; i < len(t.AssistRoleList); i++ {
		t.AssistRoleList[i] = 0
	}
	for index, roleId := range roleIdList {
		t.AssistRoleList[index] = roleId
	}
}

func (u *User) InitTeam(initRoleId []int32) {
	initTeamNum := gdconf.GetConstInt("TEAMINITIALNUM")
	if initTeamNum == 0 || int(initTeamNum) > len(u.Team) {
		logger.Error("init team num error, initTeamNum: %v", initTeamNum)
		initTeamNum = 1
	}
	for i := 0; i < int(initTeamNum); i++ {
		u.AddTeam()
	}
	u.SetActiveTeamId(1)
	team := u.GetTeam(1)
	if len(initRoleId) > 4 {
		initRoleId = initRoleId[:4]
	}
	team.SetFightRoleList(initRoleId)
}

func (u *User) GetActiveTeamId() int32 {
	return u.TeamId
}

func (u *User) SetActiveTeamId(teamId int32) {
	if u.GetTeam(teamId) == nil {
		logger.Error("invalid teamId: %v, uid: %v", teamId, u.GetUid())
		return
	}
	u.TeamId = teamId
}

func (u *User) GetTeam(teamId int32) *Team {
	for i := 0; i < len(u.Team); i++ {
		team := &(u.Team[i])
		if !team.IsUse() {
			continue
		}
		if team.GetId() == teamId {
			return team
		}
	}
	return nil
}

func (u *User) GetTeamList() []*Team {
	list := make([]*Team, 0)
	for i := 0; i < len(u.Team); i++ {
		team := &(u.Team[i])
		if !team.IsUse() {
			continue
		}
		list = append(list, team)
	}
	sort.Slice(list, func(i, j int) bool {
		return list[i].GetId() < list[j].GetId()
	})
	return list
}

func (u *User) AddTeam() *Team {
	for i := 0; i < len(u.Team); i++ {
		team := &(u.Team[i])
		if team.IsUse() {
			continue
		}
		teamNum := len(u.GetTeamList())
		team.Id.NewVal = int32(teamNum + 1)
		team.SetName("队伍" + strconv.Itoa(teamNum+1))
		return team
	}
	return nil
}

func (u *User) CheckTeam4Trail(trailGroupId int32, roleList []int32) bool {
	var trailConfigs = gdconf.GetTrailRoleConfigMap4GroupId(trailGroupId)
	if trailConfigs == nil {
		return false
	}
	for _, v := range trailConfigs {
		for i := 0; i < len(roleList); i++ {
			if i == int(v.Position-1) {
				continue
			}
			if v.RoleId == roleList[i] {
				return false
			}
		}
	}
	return true
}

func (u *User) CheckCurTeam4Trail(trailGroupId int32) bool {
	var pTeam = u.GetTeam(u.GetActiveTeamId())
	if pTeam == nil {
		logger.Error("Active Team is nil! uid: %v", u.GetUid())
		return false
	}
	var roleIdList = make([]int32, 0)
	roleIdList = append(roleIdList, pTeam.GetFightRoleList()...)
	roleIdList = append(roleIdList, pTeam.GetAssistRoleList()...)
	return u.CheckTeam4Trail(trailGroupId, roleIdList)
}

func (u *User) PacketUserTeamAll(rsp *pb.SC_Fetch) {
	rsp.Team = u.PacketPbTeamData()
}

func (t *Team) PacketPbTeam() *pb.Team {
	roleIdList := make([]int32, 0)
	for _, v := range t.GetFightRoleList() {
		roleIdList = append(roleIdList, v)
	}
	for _, v := range t.GetAssistRoleList() {
		roleIdList = append(roleIdList, v)
	}
	return &pb.Team{
		TeamId:     t.Id.NewVal,
		Name:       t.GetName(),
		RoleIdList: roleIdList,
	}
}

func (u *User) PacketPbTeamData() *pb.TeamData {
	teamList := make([]*pb.Team, 0)
	for _, team := range u.GetTeamList() {
		teamList = append(teamList, team.PacketPbTeam())
	}
	return &pb.TeamData{
		ActiveTeamId: u.GetActiveTeamId(),
		TeamList:     teamList,
	}
}
